package co.fitstart.admin.web.controller.course;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.BusinessException;
import com.demo2do.core.support.Result;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.JsonUtils;

import co.fitstart.admin.service.CourseRoundService;
import co.fitstart.admin.service.CourseScheduleService;
import co.fitstart.admin.service.DataService;
import co.fitstart.admin.service.OfflineRoundService;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.GroupRoundAttr;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.principal.Principal;

@Controller
@RequestMapping("/group-rounds/{roundCode}")
public class GroupRoundEditController {

    private static final Logger logger = LoggerFactory.getLogger(GroupRoundEditController.class);
    
    @Autowired
    private OfflineRoundService offlineRoundService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<Principal> principalService;
    
    @Autowired
    private CourseRoundService courseRoundService;
    
    @Autowired
    private CourseScheduleService courseScheduleService;
    
    /**
     * Display edit group round panel
     * 
     * @param roundCode 
     * 
     * @return
     */
    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public ModelAndView editGroupBasic(@PathVariable("roundCode") String roundCode) {
        
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-edit");
        
        CourseRound courseRound = offlineRoundService.loadCourseRound(roundCode);
        
        modelAndView.addObject("courseRound", courseRound);
        
        return modelAndView;
    }
    
    /**
     * Do edit group round
     * 
     * @param roundCode
     * @param groupRoundAttr
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.PATCH)
    public @ResponseBody String onEditGroupBasic(@RequestParam(value = "roundCode") String roundCode,
                                                 GroupRoundAttr groupRoundAttr) {
        
        Result result = new Result();
        
        try {
            
            offlineRoundService.editGroupBasic(roundCode, groupRoundAttr);
            
            result.success().message("编辑信息成功");
            
        } catch (Exception e) {
            
            result.fail().message("编辑信息失败");
            
            logger.error("#onEdit() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * View round bind coach page
     * 
     * @param roundCode
     * @param dayhour 
     * @return
     */
    @RequestMapping(value = "/bind-coach", method = RequestMethod.GET)
    public ModelAndView bindCoach(@PathVariable("roundCode") String roundCode,
                                  @RequestParam("dayhour") String dayhour) {
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-bind-coach");
        
        modelAndView.addObject("roundCode", roundCode);
        modelAndView.addObject("dayhour", dayhour);
        
        return modelAndView;
    }
    
    /**
     * Do bind coach
     * 
     * @param roundCode 
     * @param coachId 
     * @param dayhour 
     * @return
     */
    @RequestMapping(value = "/bind-coach", method = RequestMethod.PATCH)
    public @ResponseBody String onBindCoach(@PathVariable("roundCode") String roundCode,
                                            @RequestParam(value = "coachId") Long coachId,
                                            @RequestParam(value = "dayhour") String dayhour) {
        
        Result result = new Result();
        
        try {
            
            // step1 load selected coach
            Principal coach = principalService.load(Principal.class, coachId);
            
            // setp2 check coach is available or not by dayhour
            result = courseRoundService.validateCoach(coach, dayhour);
            
            // step3 do bind coach if validateCoach success
            if(result.isValid()) {
                offlineRoundService.bindGroupRoundCoach(coach, roundCode, dayhour);
                result.success().message("分配教练成功");
            }
            
        } catch (Exception e) {
            
            result.fail().message("分配教练失败");
            
            logger.error("#listStudent() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    
    /**
     * View round bind coach page
     * 
     * @param roundCode
     * @param dayhour 
     * @return
     */
    @RequestMapping(value = "/change-time", method = RequestMethod.GET)
    public ModelAndView changeTime(@PathVariable("roundCode") String roundCode,
                                   @RequestParam("dayhour") String dayhour) {
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-change-time");
        
        List<CourseRound> courseRounds = offlineRoundService.listCourseRound(roundCode);
        List<CourseSchedule> courseSchedules = courseScheduleService.listCourseSchedule(courseRounds, dayhour);
        modelAndView.addObject("schedule", courseSchedules.get(0));
        
        modelAndView.addObject("roundCode", roundCode);
        modelAndView.addObject("dayhour", dayhour);
        
        modelAndView.addObject("site", courseRounds.get(0).getSite());
        
        return modelAndView;
    }
    
    /**
     * Do bind coach
     * 
     * @param roundCode 
     * @param dayhour 
     * @param day 
     * @param hour 
     * @return
     */
    @RequestMapping(value = "/change-time", method = RequestMethod.PATCH)
    public @ResponseBody String onChangeTime(@PathVariable("roundCode") String roundCode,
                                             @RequestParam(value = "dayhour") String dayhour,
                                             @RequestParam("day") @DateTimeFormat(pattern = "yyyy-MM-dd") Date day,
                                             @RequestParam("hour") String hour) {
        
        Result result = new Result();
        
        try {
            
            // step1 list selected course schedule
            List<CourseRound> courseRounds = offlineRoundService.listCourseRound(roundCode);
            List<CourseSchedule> courseSchedules = courseScheduleService.listCourseSchedule(courseRounds, dayhour);
            
            String selectedDayHour = DateFormatUtils.format(day) + "|" + hour;
            
            Principal coach = courseSchedules.get(0).getCoach();
            
            // setp2 check coach is available or not by dayhour
            List<String> dayhours = courseRoundService.getDayhours(StringUtils.replace(dayhour, "|", " "));
            if(StringUtils.equalsIgnoreCase(dayhour, selectedDayHour) || (dayhours.contains(selectedDayHour) && courseRoundService.validateCoach(coach, dayhours, dayhour, selectedDayHour)) ) {
                result.success();
            } else if(coach != null) {
                result = courseRoundService.validateCoach(coach,selectedDayHour);
            }
            
            // step3 do bind coach if validateCoach success
            if(result.isValid()) {
                courseRoundService.changeScheduleTime(courseSchedules, day, hour, CourseType.GROUP);
                result.success().message("更改课程时间成功");
            }
            
        } catch (BusinessException e) {
            result.fail().message(e.getMessage());
        }catch (Exception e) {
            
            result.fail().message("更改课程时间失败");
            
            logger.error("#listStudent() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * View append round panel
     * 
     * @param roundCode
     * @return
     */
    @RequestMapping(value = "/rounds/create", method = RequestMethod.GET)
    public ModelAndView appendRound(@PathVariable("roundCode") String roundCode) {
        
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-create-student");
        
        CourseRound courseRound = offlineRoundService.loadCourseRound(roundCode);
        List<CourseRound> courseRounds = offlineRoundService.listCourseRound(courseRound.getCourse(), RoundStatus.PREPARE);
        
        modelAndView.addObject("roundCode", roundCode);
        modelAndView.addObject("courseRounds", courseRounds);
        
        return modelAndView;
        
    }
    
    /**
     * Do append round to group
     * 
     * @param roundCode
     * @param roundId 
     * @return
     */
    @RequestMapping(value = "/rounds", method = RequestMethod.POST)
    public @ResponseBody String onAppendRound(@PathVariable("roundCode") String roundCode,
                                              @RequestParam("roundId") Long roundId) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
            
            if(StringUtils.isNotEmpty(courseRound.getCode()) && courseRound.getCourseStatus().isAvaliable()) {
                result.fail().message("新增学员状态异常");
                return JsonUtils.toJsonString(result);
            }
            
            offlineRoundService.addGroupRound(courseRound, roundCode);
            
            result.success().message("添加学员成功");
            
        } catch (Exception e) {
            
            result.fail().message("添加学员失败");
            
            logger.error("#onCreate() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * View drop round from group panel
     * 
     * @param roundCode 
     * @param roundId 
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/drop", method = RequestMethod.GET)
    public ModelAndView drop(@PathVariable("roundCode") String roundCode,
                             @PathVariable("roundId") Long roundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-drop");
        
        CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
        
        modelAndView.addObject("courseRound",courseRound);
        
        return modelAndView;
        
    }
    
    /**
     * Do drop round from group
     * 
     * @param roundCode
     * @param roundId 
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/drop", method = RequestMethod.PATCH)
    public @ResponseBody String onDrop(@PathVariable("roundCode") String roundCode,
                                       @PathVariable("roundId") Long roundId,
                                       @RequestParam("isRefund") Boolean isRefund,
                                       @RequestParam(value = "refundPrice", required = false) BigDecimal refundPrice) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
            
            // validate
            if(!StringUtils.equalsIgnoreCase(courseRound.getCode(), roundCode)) {
                result.fail().message("退课学员参数异常");
                return JsonUtils.toJsonString(result);
                
            }
            
            offlineRoundService.dropCourse(courseRound, isRefund, refundPrice);
            
            result.success().message("学员退课成功");
            
        } catch (Exception e) {
            
            result.fail().message("学员退课失败");
            
            logger.error("#onDrop() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * View group round transfer panel
     * 
     * @param roundCode 
     * @param roundId 
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/transfer", method = RequestMethod.GET)
    public ModelAndView transfer(@PathVariable("roundCode") String roundCode,
                                 @PathVariable("roundId") Long roundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-transfer");
        
        List<CourseRound> courseRounds = offlineRoundService.listCourseRound(CourseType.GROUP);
        
        modelAndView.addObject("roundCode", roundCode);
        modelAndView.addObject("roundId", roundId);
        
        modelAndView.addObject("courseRounds", courseRounds);
        
        return modelAndView;
        
    }
    
    /**
     * Do group round transfer
     * 
     * @param roundId 
     * @param roundCode 
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/transfer", method = RequestMethod.PATCH)
    public @ResponseBody String onTransfer(@PathVariable("roundId") Long roundId,
                                           @RequestParam("roundCode") String roundCode) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
            
            if(offlineRoundService.listCourseRound(courseRound.getCode()).size() == 1) {
                result.fail().message("此团课只有一个人，不能转团");
                return JsonUtils.toJsonString(result);
            }
            
            offlineRoundService.transfer(courseRound, roundCode);
            
            result.success().message("学员转团成功");
            
        } catch (Exception e) {
            
            result.fail().message("学员转团失败");
            
            logger.error("#onTransfer() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
    
    /**
     * 
     * @param roundCode
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/stop-camp", method = RequestMethod.GET)
    public ModelAndView stopCamp(@PathVariable("roundCode") String roundCode, 
                                 @PathVariable("roundId") Long courseRoundId) {
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-stop-camp");
        
        modelAndView.addObject("roundCode", roundCode);
        modelAndView.addObject("roundId", courseRoundId);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param roundCode
     * @param courseRoundId
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/stop-camp", method = RequestMethod.PATCH)
    public @ResponseBody String onStopCamp(@PathVariable("roundCode")String roundCode, 
                                           @PathVariable("roundId") Long courseRoundId) {
        
        Result result = new Result();
        
        try{
            
            CourseRound courseRound = courseRoundService.loadCourseRound(courseRoundId);
            
            courseRoundService.stopCamp(courseRound);
            
            result.success().message("手动结营成功");
        
        } catch(Exception e){
            
            logger.error("#onStopCamp - ", e);
            
            result.fail().message("手动结营失败");
        }
        
        return JsonUtils.toJsonString(result);
    }

    /**
     * View remove student from group panel
     * 
     * @param roundCode 
     * @param roundId 
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/remove", method = RequestMethod.GET)
    public ModelAndView remove(@PathVariable("roundCode") String roundCode,
                               @PathVariable("roundId") Long roundId) {
        
        ModelAndView modelAndView = new ModelAndView("course/group/group-round-remove");
        
        modelAndView.addObject("roundCode",roundCode);
        modelAndView.addObject("roundId", roundId);
        
        return modelAndView;
        
    }
    
    /**
     * Do drop round from group
     * 
     * @param roundCode
     * @param roundId 
     * @return
     */
    @RequestMapping(value = "/rounds/{roundId}/remove", method = RequestMethod.PATCH)
    public @ResponseBody String onRemove(@PathVariable("roundCode") String roundCode,
                                         @PathVariable("roundId") Long roundId) {
        
        Result result = new Result();
        
        try {
            
            CourseRound courseRound = courseRoundService.loadCourseRound(roundId);
            
            // validate
            if(!StringUtils.equalsIgnoreCase(courseRound.getCode(), roundCode)) {
                result.fail().message("移除学员参数异常");
                return JsonUtils.toJsonString(result);
                
            }
            
            offlineRoundService.removeCourse(courseRound);
            
            result.success().message("移除学员成功");
            
        } catch (Exception e) {
            
            result.fail().message("移除学员失败");
            
            logger.error("#onRemove() error ", e);
            
        }
        
        return JsonUtils.toJsonString(result);
    }
}
